package wili.logic;

import wili.c.Ca;
import wili.c.Src9a;
import wili.c.Str9a;

/**
 * 单行逻辑式 ~>缩进表达 logic expression has and or node。 仅关注括号和逻辑联结词，不深入命题。
 */
public class ToIndentLogicExp {
	public ToIndentLogicNode root;

	Cont21 cont;

	/**
	 * lineExp：单行表达式；indentExp：缩进表达式
	 */
	final String lineExp;

	/**
	 * @return single line logic expression.
	 */
	public String toString() {
		return lineExp;
	}

	/**
	 * ...so can 单行表达 ~> 逻辑式的缩进表达
	 */
	public ToIndentLogicExp(String line) {
		line = Str9a.removeRedundantBracket('(', ')', line.trim());
		//({/ObjType} eq 13 or {/ObjType} eq 14) and ({/VHandCompanyWTax} eq 'Y') and ( {/VLawsSet} eq 'BR')
		//({/ObjType} eq 13  or  {/ObjType} eq 14)  and  ({/VH and CompanyWTax} eq 'Y')  and  ( {/VLawsSet} eq 'BR')
		line = line.replaceAll("([^\\w\\s])(and|or)([^\\w\\s])", "$1 $2 $3")
				.replaceAll("\\s(and|or)([^\\w\\s])", " $2 $3").replaceAll("([^\\w\\s])(and|or)\\s", "$1 $2 ");
		if (line.startsWith("{="))
			line = line.substring(2, line.length() - 1);
		line = line.trim();
		String and = " and ", or = " or ";
		if (line.contains(" && ") || line.contains(" || ")) {
			and = "&&";
			or = "||";
			line = line.replaceAll("\\s+and\\s+", " && ").replaceAll("\\s+or\\s+", " || ");
		}
		if (Boolean.FALSE) {//eg.确保单词算符前后有空格： "and(b or c)" ~>"and (b or c)"
			line = line.replaceAll("\\s(and|or|eq|ne|gt|lt|ge|le)([^\\w\\s])", " $1 $2");
			line = line.replaceAll("([^\\w\\s])(and|or|eq|ne|gt|lt|ge|le)\\s", "$1 $2 ");
			line = line.replaceAll("([\\W])and([\\W])", "&&").replaceAll("([\\W])or([\\W])", "||").trim();
		}
		Cont21 cont = new Cont21(and, or);
		line = Str9a.removeOutmostBracket(line);
		if ("asdf".isEmpty()) {
			Src9a.SubStrMap ret = Src9a.replace_javaComment_and_quotes_withSameLengthSpace(line);
			String fm2 = ret.resultSt;
			cont.setExprSt(fm2);
		} else {
			cont.setExprSt(line);
		}
		//
		this.cont = cont;
		this.lineExp = line;
		this.root = new ToIndentLogicNode(cont, 0, cont.expSt.length());
	}

	static void test() {
		String[] ff = { //
				"${Status} !== 'C' && (${ObjType} === '13' || ${ObjType} === '14' || ${ObjType} === '15' || ${ObjType} === '16' || ${ObjType} === '540000006' || ${ObjType} === '112' || ${ObjType} === '22' || ${ObjType} === '234000031')", //
				"{Status} ne 'C' and ({ObjType} eq '13' or {ObjType} eq '14' or {ObjType} eq '15' or {ObjType} eq '16' or {ObjType} eq '540000006' or {ObjType} eq '112' or {ObjType} eq '22' or {ObjType} eq '234000031')",
				"{ObjType} eq '13' or {ObjType} eq '14' or {ObjType} eq '15'", "a && (b || c)", //
				"a && !(b || !(c && !d)) || f", //
				"${= a and b}", //
				"${=!${view>/$EditMode/viewMode} && (['17','23'].includes(${/ObjType}) && ${/DocStatus} !== 'C' || ['-10000','13','14','15','16'].includes(${/ObjType}) && !['C','O'].includes(${/DocStatus}) || ['1470000113','540000006','22'].includes(${/ObjType}) && !['C'].includes(${/DocStatus}) || ['18', '19', '20','21'].includes(${/ObjType}) && !['C'].includes(${/DocStatus})) && !(${view>/$EditMode/editMode} && ['18', '19', '20','21'].includes(${/ObjType}))}",
				//
				"false eq f and e", //
				"false eq ({VDocStatus} eq 'C' and ({ObjType} eq 1470000113 or {ObjType} eq 540000006 or {ObjType} eq 22)) and  (({VDocStatus} eq 'O') or ({VDocStatus} eq 'OP') or ({VDocStatus} eq 'UNA') or ({VDocStatus} eq 'DELIVERED') or ({VDocStatus} eq 'C' and ({/CANCELED} ne 'Y' and {/CANCELED} ne 'C') and ({ObjType} ne '23' and {ObjType} ne '17'))) and ({ObjType} eq '112' or {ObjType} eq '540000006' or {ObjType} eq '22' or {ObjType} eq '20' or {ObjType} eq '18' or {ObjType} eq '21' or {ObjType} eq '19' or {ObjType} eq '234000032' or ({ObjType} eq '1470000113' and {VDocCopiedTo} ne 'Y'))", //
				"(({VDocStatus} eq 'O') or ({VDocStatus} eq 'OP') or ({VDocStatus} eq 'UNA') or ({VDocStatus} eq 'DELIVERED') or ({VDocStatus} eq 'C' and ({/CANCELED} ne 'Y' and {/CANCELED} ne 'C') and ({ObjType} ne '23' and {ObjType} ne '17' and {ObjType} ne '234000031'))) and ({ObjType} eq '17' or {ObjType} eq '112' or {ObjType} eq '23' or {ObjType} eq '15' or {ObjType} eq '13' or {ObjType} eq '14' or {ObjType} eq '16' or {ObjType} eq '540000006' or {ObjType} eq '234000031')", //
				"a,(c|d),e,f2", //
				"a,b|(d,f)|e", //
				"(c|(f,e))", //
				"a,b|(c|(d,(e|f))),g", //
				"a,(b|(c|f)),g", //或有或子
				"a,(b,e,(f|g))", //与有与子
				"(a,(b,c),(d,e)))", //
				"((a) or (t) or (c) or (d) or (e and (f) and (g))) and (h or i or j or k or m or n or o or p  or q)", //
				"(({VDocStatus} eq 'O') or ({VDocStatus} eq 'OP') or ({VDocStatus} eq 'UNA') or ({VDocStatus} eq 'DELIVERED') or ({VDocStatus} eq 'C' and ({/CANCELED} ne 'Y' and {/CANCELED} ne 'C') and ({ObjType} ne '23' and {ObjType} ne '17'))) and ({ObjType} eq '112' or {ObjType} eq '540000006' or {ObjType} eq '22' or {ObjType} eq '20' or {ObjType} eq '18' or {ObjType} eq '21' or {ObjType} eq '19' or {ObjType} eq '234000032'  or {ObjType} eq '1470000113')" };
		for (int i = 0; i < ff.length; i++) {
			String lineExp = ff[i];
			Cont21 cont = new Cont21();
			ToIndentLogicExp obj = new ToIndentLogicExp(lineExp);
			String ret = obj.root.toIndentString(1);
			Ca.log("---------ToIndentLogicExp:" + i + "\n" + lineExp);
			Ca.log(ret);
			break;
		}
	}

	public static void main(String[] args) {
		test();
	}
}
